using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace TestGame
{
	public class Camera
	{
		public static Camera m_Active = null;
		protected float m_Zoom;
		protected Matrix m_Transform, m_TransformInvert;
		protected Vector2 m_Pos, m_PrePos, m_TargetPos;
		bool m_MovingTarget;
		//TODO: Add locking the camera to a unit. Include Unit location by passing the objects location through the unit manager
		bool m_Locked = false;
		//TODO: Limit to bounds of a screen by including a rectangle into the Variable. 
		bool m_LimitToBounds = false;
		protected float m_rotation;
		protected float m_SpeedScale;
		protected GraphicsDevice m_Graphics;

		public Camera (GraphicsDevice graphics)
		{
			m_Graphics = graphics;
			m_Zoom = 1.0f;
			m_rotation = 0.0f;
			m_Pos = Vector2.Zero;
			m_SpeedScale = 1;
			m_MovingTarget = false;
		}
		public void MakeActive()
		{
			m_Active = this;
		}
		public float Zoom
		{
			get {return m_Zoom;}
			set 
			{
				m_Zoom = value; 
				if (m_Zoom < 0.1f)
					m_Zoom = 0.1f;
				UpdateTransform ();
			}
		}
		public float Rotation
		{
			get{ return m_rotation;}
			set
			{
				m_rotation = value;
				UpdateTransform ();
			}
		}
		public float SpeedScale
		{
			get{ return m_SpeedScale;}
			set{ m_SpeedScale = value;}
		}
		public GraphicsDevice GraphicsDevice
		{
			get { return m_Graphics;}
			set { m_Graphics = value;}
		}
		public void Move(Vector2 amount)
		{
			m_Pos += amount * m_SpeedScale;
			UpdateTransform ();
		}
		public void MoveSmooth(Vector2 Target)
		{
			m_PrePos = m_Pos;
			m_TargetPos = Target;
			m_MovingTarget = true;
		}
		public void Update(GameTime gametime)
		{
			if (!m_MovingTarget)
				return;
			if (MathHelper.Distance (m_PrePos.X, m_TargetPos.X) < 0.5f) 
			{
				m_MovingTarget = false;
				return;
			}
			m_PrePos.X = MathHelper.Lerp (m_PrePos.X, m_TargetPos.X, 0.1f);
			m_PrePos.Y = MathHelper.Lerp (m_PrePos.Y, m_TargetPos.Y, 0.1f);
			m_Pos.X = MathHelper.Lerp (m_Pos.X, m_PrePos.X, 0.1f);
			m_Pos.Y = MathHelper.Lerp (m_Pos.Y, m_PrePos.Y, 0.1f);
			UpdateTransform ();
		}
		public Vector2 Position
		{
			get { return m_Pos;}
			set 
			{ 
				m_Pos = value;
				UpdateTransform ();
			}
		}
		public Matrix GetTransform
		{
			get { return m_Transform; }
		}
		public Matrix GetTransformInvert
		{
			get { return m_TransformInvert; }
		}
		void UpdateTransform ()
		{
			m_Transform = 
				Matrix.CreateTranslation (new Vector3 (-m_Pos.X, -m_Pos.Y, 0.0f)) *
				Matrix.CreateRotationZ (Rotation) *
				Matrix.CreateScale (Zoom) * 
				Matrix.CreateScale (-1, 1, 1) *
				Matrix.CreateTranslation (new Vector3 (m_Graphics.Viewport.Width * 0.5f, m_Graphics.Viewport.Height * 0.5f, 0.0f));
			m_TransformInvert = Matrix.Invert (m_Transform);
		}
	}
}

